﻿#include "scriptmanager.h"
#include "cmainframe.h"
#include "nodemanager/wbasenode.h"
#include "nodemanager/wmountnode.h"
#include "nodemanager/wsignallampnode.h"
#include "nodemanager/wswitchnode.h"
#include "nodemanager/wnodemanager.h"
#include "locomanager/locomanager.h"
#include "gui/guimanager.h"
#include "nodemanager/crouteconditions.h"

#include <functional>
#include <memory>

initialiseSingleton(ScriptManager);

ScriptManager::ScriptManager()
    : m_lua_state(NULL)
{

}

ScriptManager::~ScriptManager()
{
    lua_exit();
}

/// 初始化
bool ScriptManager::lua_init()
{
    m_lua_state = luaL_newstate();
    if(m_lua_state)
    {
        luaL_openlibs(m_lua_state);
        luaopen_cjson(m_lua_state);

        // 完全停止垃圾回收
        lua_gc(m_lua_state, LUA_GCSTOP, 0);

        LOGI("lua_init successed.");
    }

    return m_lua_state != NULL ? true : false;
}

/// 清除gc
void ScriptManager::lua_clear()
{
    if (m_lua_state == NULL) return;  // Safety check

    lua_settop(m_lua_state, 0);

    // 1. 恢复 GC
    lua_gc(m_lua_state, LUA_GCRESTART, 0);

    // 1. First, do a full collection
    lua_gc(m_lua_state, LUA_GCCOLLECT, 0);
    lua_gc(m_lua_state, LUA_GCCOLLECT, 0);

    // 3. More gentle GC approach
    lua_gc(m_lua_state, LUA_GCSTOP, 0);
}

/// 退出
void ScriptManager::lua_exit()
{
    if (m_lua_state != NULL)
    {
        // 1. 清除所有栈对象
        lua_settop(m_lua_state, 0);

        lua_clear();

        // 3. 关闭前检查 cjson 等模块的清理
        lua_pushnil(m_lua_state);
        lua_setglobal(m_lua_state, "cjson");  // 清除全局变量

        // 4. Close the state
        lua_close(m_lua_state);
        m_lua_state = NULL;

        LOGI("lua_exit succeeded.");
    }
}

/**
 * @brief 为 Lua 状态创建独立环境
 * @param inheritGlobals 是否继承全局函数和库（true=继承，false=完全干净的环境）
 * @return 是否成功创建独立环境
 */
bool ScriptManager::CreateIsolatedLuaEnvironment(bool inheritGlobals)
{
    if (!m_lua_state) return false;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 1. 清除栈上所有内容
    lua_settop(m_lua_state, 0);

    //lua_gc(m_lua_state, LUA_GCRESTART, 0);

    // 2. 创建新的环境表
    lua_newtable(m_lua_state);  // 创建环境表

    if (inheritGlobals)
    {
        // 3a. 如果需要继承全局函数，设置元表访问全局环境
        lua_getglobal(m_lua_state, "_G");  // 获取全局表（替代 LUA_GLOBALSINDEX）
        lua_setmetatable(m_lua_state, -2); // 设置为新环境的元表

        // 可选：复制常用基础库到新环境
        static const char* const basicLibs[] = {
            "_G", "math", "table", "string", nullptr
        };

        for (const char* const* lib = basicLibs; *lib; ++lib)
        {
            lua_getglobal(m_lua_state, *lib);
            lua_setfield(m_lua_state, -2, *lib);
        }
    }
    else
    {
        // 3b. 或者创建完全干净的环境
        lua_newtable(m_lua_state);  // 创建空的元表
        lua_setmetatable(m_lua_state, -2);
    }

    // 4. 在 Lua 5.2+ 中设置环境的新方法
    // 首先将环境表存储在注册表中
    lua_pushvalue(m_lua_state, -1);  // 复制环境表
    lua_setfield(m_lua_state, LUA_REGISTRYINDEX, "my_isolated_env");  // 存储在注册表中

    // 然后为当前线程设置环境
    lua_rawgeti(m_lua_state, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);  // 获取全局环境
    lua_pushvalue(m_lua_state, -2);  // 推入我们的环境表
    lua_setmetatable(m_lua_state, -2);  // 设置为全局环境的元表
    lua_pop(m_lua_state, 1);  // 弹出全局环境

    // 5. 执行垃圾回收确保干净状态
    //lua_gc(m_lua_state, LUA_GCCOLLECT, 0);

    // 完全停止垃圾回收
    //lua_gc(m_lua_state, LUA_GCSTOP, 0);

    lua_clear();

    return true;
}

/// 导入指定文件脚本并执行
bool ScriptManager::exe_lua_string_for_file(wxString scriptFile)
{
    if(!wxFileExists(scriptFile)) return false;

   //std::lock_guard<std::mutex> lock(m_luastateMutex);

    wxMemoryBuffer pMemorybuffer;
    if(!ReadFileToMemoryBuffer(scriptFile,pMemorybuffer))
    {
        LOGW(wxString(wxT("脚本文件导入失败:")+scriptFile).ToUTF8().data());
        return false;
    }

    wxString tmpfilename = scriptFile.Mid(scriptFile.find_last_of("/")+1);

    if(pMemorybuffer.IsEmpty() ||
       !exe_lua_string(pMemorybuffer,tmpfilename))
    {
        LOGW(wxString(wxT("脚本文件导入失败:")+scriptFile).ToUTF8().data());
        return false;
    }
    else
    {
        LOGI(wxString(wxT("脚本文件导入成功:")+scriptFile).ToUTF8().data());
    }

    return true;
}

/// 导入指定目录所有脚本并执行
bool ScriptManager::exe_lua_string_for_path(wxString scriptPath)
{
    if(scriptPath == "")
        return false;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    wxVector<wxString> pdecPaths;
    if(ListFilesInDirectory(scriptPath,pdecPaths))
    {
        for(int i=0;i<pdecPaths.size();i++)
        {
            wxMemoryBuffer pMemorybuffer;
            if(!ReadFileToMemoryBuffer(pdecPaths[i],pMemorybuffer))
            {
                LOGW(wxString(wxT("脚本文件导入失败:")+pdecPaths[i]).ToUTF8().data());
                continue;
            }

            wxString tmpfilename = pdecPaths[i].Mid(pdecPaths[i].find_last_of("/")+1);

            if(pMemorybuffer.IsEmpty() ||
               !exe_lua_string(pMemorybuffer,tmpfilename))
            {
                LOGW(wxString(wxT("脚本文件导入失败:")+pdecPaths[i]).ToUTF8().data());
               return false;
            }
            else
            {
               LOGI(wxString(wxT("脚本文件导入成功:")+pdecPaths[i]).ToUTF8().data());
            }
        }
    }

    return true;
}

/// 执行脚本
bool ScriptManager::exe_lua_string(wxMemoryBuffer& buffer,wxString filename)
{
    if (m_lua_state == NULL || buffer.IsEmpty())
        return false;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 加载 Lua 代码
    if (luaL_loadbuffer(m_lua_state,
                        (const char*)buffer.GetData(),
                        buffer.GetDataLen(),
                        "interlocker4")) {
        const char* pErrorMsg = lua_tostring(m_lua_state, -1);
        if (pErrorMsg) {
            wxString errStr = wxString::Format(wxT("Lua load error:%s:%s"),
                                               filename,
                                               pErrorMsg);
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,errStr.utf8_string());
            LOGE(errStr.ToUTF8().data());
        }
        lua_pop(m_lua_state, 1); // 弹出错误信息
        return false;
    }

    // 执行 Lua 代码
    int ret = lua_pcall(m_lua_state, 0, 0, 0);
    if (ret != LUA_OK) {
        const char* pErrorMsg = lua_tostring(m_lua_state, -1);
        if (pErrorMsg) {
            // 获取调用栈信息
            luaL_traceback(m_lua_state, m_lua_state, pErrorMsg, 1);
            const char* traceback = lua_tostring(m_lua_state, -1);
            wxString errStr = wxString::Format(wxT("Lua runtime error:%s,%s"),
                                               filename,
                                               traceback);
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,errStr.ToUTF8().data());
            LOGE(errStr.ToUTF8().data());
            lua_pop(m_lua_state, 2); // 弹出错误信息和 traceback
        } else {
            LOGE("Lua runtime error (no message)");
        }
        return false;
    }

    //LOGI("exe_lua_string success.");
    return true;
}

/// 调用结点的鼠标事件接口
void ScriptManager::callLuaFunctionWithBaseNodeMouseEvent(const char* nodeName,wxMouseEvent event)
{
    if(m_lua_state == NULL || nodeName == "") return;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    //wxString decFunction = wxString::Format(wxT("onMouseEvent_%s"),nodeName);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state,nodeName);

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func(event);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format(wxT("ScriptManager::cllLuaFunctionWithBaseNodeMouseEvent:%s:%s"),
                                                                 wxString::FromUTF8(nodeName),
                                                                 wxString::FromUTF8(e.what())).ToUTF8().data());
        }
    }
}

/// 调用结点的更新接口
void ScriptManager::callLuaFunctionWithBaseNodeUpdate(const char* nodeName)
{
    if(m_lua_state == NULL || nodeName == "") return;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    //wxString decFunction = wxString::Format(wxT("update_%s"),nodeName);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state,nodeName);

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func();
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format(wxT("ScriptManager::callLuaFunctionWithBaseNodeDraw:%s:%s"),
                                                                 wxString::FromUTF8(nodeName),
                                                                 wxString::FromUTF8(e.what())).ToUTF8().data());
        }
    }
}

/// 调用结点的绘制接口
void ScriptManager::callLuaFunctionWithBaseNodeDraw(maindrawscene *pmaindrawscene,const char* nodeName)
{
    if(pmaindrawscene == NULL || m_lua_state == NULL || nodeName == "") return;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    //wxString decFunction = wxString::Format(wxT("draw_%s"),nodeName);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state,nodeName);

    if (func && func.isFunction()) {
        try {            
            // 调用Lua函数并传递wxPoint对象
            func(pmaindrawscene);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format(wxT("ScriptManager::callLuaFunctionWithBaseNodeDraw:%s:%s"),
                                                                 wxString::FromUTF8(nodeName),
                                                                 wxString::FromUTF8(e.what())).ToUTF8().data());
        }
    }
}

/// 调用lua系统初始接口
void ScriptManager::callLuaFunctionWithSystemInit()
{
    if(m_lua_state == NULL) return;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state, "initsystem");

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func();
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format(wxT("ScriptManager::callLuaFunctionWithSystemInit: %s"),
                                                                 wxString::FromUTF8(e.what())).ToUTF8().data());
        }
    }
}

/// 调用lua系统鼠标事件接口
void ScriptManager::callLuaFunctionWithSystemMouseEvent(int selMode,wxMouseEvent event)
{
    if(m_lua_state == NULL) return;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state, "onMouseEvent");

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func(selMode,event);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format(wxT("ScriptManager::callLuaFunctionWithSystemMouseEvent: %s"),
                                                                 wxString::FromUTF8(e.what())).ToUTF8().data());
        }
    }
}

/// 调用lua系统更新接口
void ScriptManager::callLuaFuncitonWithSystemUpdate(void)
{
    if(m_lua_state == NULL) return;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state, "updatesystem");

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func();
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format(wxT("ScriptManager::callLuaFuncitonWithSystemUpdate: %s"),
                                                                 wxString::FromUTF8(e.what())).ToUTF8().data());
        }
    }
}

/// 调用lua系统网络消息接口
void ScriptManager::callLuaFunctionWithNetworkMsg(int msgType,const char* msg)
{
    if(m_lua_state == NULL) return;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state, "onNetMessageEvent");

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func(msgType,msg);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format(wxT("ScriptManager::callLuaFunctionWithNetworkMsg: %s"),
                                                                 wxString::FromUTF8(e.what())).ToUTF8().data());
        }
    }
}

/// 调用lua主绘制接口
void ScriptManager::callLuaFunctionWithMainDrawScene(maindrawscene *pmaindrawscene)
{
    if(pmaindrawscene == NULL || m_lua_state == NULL) return;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state, "maindrawscene");

    if (func.isFunction()) {
        try {
            // 调用Lua函数并传递wxPoint对象
            func(pmaindrawscene);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format(wxT("ScriptManager::callLuaFunctionWithMainDrawScene: %s"),
                                                                 wxString::FromUTF8(e.what())).ToUTF8().data());
        }
    }
}

/// 注册到lua
void ScriptManager::registertoLua(void)
{
    // 注册wxWidgets到脚本
    registerwxWidgetsToLua();

    // 注册系统函数到脚本中
    registerSystemFunToLua();

    // 注册主绘图到脚本
    registermaindrawsceneToLua();

    // 注册结点到脚本
    registerNodeToLua();

    /// 注册STL到脚本中
    registerSTLToLua();

    // 注册主绘制场景到lua中
    this->registerMainDrawScenetoLua(maindrawscene::getSingletonPtr());

    // 注册结点管理器为全局变量
    this->registerNodeManagertoLua(WNodeManager::getSingletonPtr());

    // 注册机车管理器为全局变量
    this->registerLocoManagertoLua(LocoManager::getSingletonPtr());

    // 注册GUI管理器为全局变量
    this->registerGUIManagertoLua(GuiManager::getSingletonPtr());

    // 注册主窗口到脚本中
    this->registerMainFrametoLua(CMainFrame::getSingletonPtr());
}

/// 注册结点管理器到lua中
void ScriptManager::registerNodeManagertoLua(WNodeManager *manager)
{
    // 注册结点为全局变量
    luabridge::setGlobal(m_lua_state,
                         manager,
                         "nodemanager");
}

/// 注册机车管理器到lua中
void ScriptManager::registerLocoManagertoLua(LocoManager *manager)
{
    // 注册结点为全局变量
    luabridge::setGlobal(m_lua_state,
                         manager,
                         "locomanager");
}

/// 注册GUI管理器到lua中
void ScriptManager::registerGUIManagertoLua(GuiManager *manager)
{
    // 注册结点为全局变量
    luabridge::setGlobal(m_lua_state,
                         manager,
                         "guimanager");
}

/// 注册主窗口到lua中
void ScriptManager::registerMainFrametoLua(CMainFrame *mainframe)
{
    // 注册结点为全局变量
    luabridge::setGlobal(m_lua_state,
                         mainframe,
                         "system");
}

/// 注册主绘制场景到lua中
void ScriptManager::registerMainDrawScenetoLua(maindrawscene *mmaindrawscene)
{
    // 注册结点为全局变量
    luabridge::setGlobal(m_lua_state,
                         mmaindrawscene,
                         "drawscene");
}

/// 注册结点到lua中
void ScriptManager::registerBaseNodetoLua(wxString nodeType,WBaseNode* basenode)
{
    if(basenode == NULL || nodeType == "") return;

    // 注册结点为全局变量
    luabridge::setGlobal(m_lua_state,
                         basenode,
                         wxString(nodeType+basenode->getName()).ToUTF8().data());
}

template <typename T> void ScriptManager::registerVector(lua_State* L, const std::string& className)
{
    luabridge::getGlobalNamespace(L)
        .beginClass<wxVector<T>>(className.c_str())
            //.addConstructor<void (*)()>()

            // 成员函数
            .addFunction("size", &wxVector<T>::size)
            .addFunction("at", static_cast<const T& (wxVector<T>::*)(size_t) const>(&wxVector<T>::at))
            .addFunction("empty", &wxVector<T>::empty)
            .addFunction("push_back", &wxVector<T>::push_back)
            .addStaticFunction("create", +[]() { return new wxVector<T>(); })
            .addFunction("destroy", std::function<void(wxVector<T>*)>([](wxVector<T>* ptr) { delete ptr; ptr = NULL; }))
        .endClass();
}

/// 注册STL到脚本中
void ScriptManager::registerSTLToLua(void)
{
    if(m_lua_state == NULL)
        return;

    registerVector<tagMountPoint>(m_lua_state,"MPVector");
    registerVector<tagSectNode*>(m_lua_state,"SNVector");
    registerVector<tagSLRouteNode>(m_lua_state,"RNVector");
    registerVector<WSignalLampNode*>(m_lua_state,"SLVector");
    registerVector<tagSwitchCondiItem>(m_lua_state,"SCVector");
    registerVector<wxString>(m_lua_state,"STVector");
    registerVector<tagRoute*>(m_lua_state,"RVector");
    registerVector<WBaseNode*>(m_lua_state,"BNVector");
    registerVector<tagRouteCondiItem*>(m_lua_state,"RCIVector");
    registerVector<const char*>(m_lua_state,"CVector");
}

/// 注册系统函数到脚本中
void ScriptManager::registerSystemFunToLua(void)
{
    if(m_lua_state == NULL)
        return;

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<CMainFrame>("CMainFrame")
        //.addConstructor<void (*)(void)>()

        // 成员函数
        .addFunction("printlog", &CMainFrame::printlog)
        //.addFunction("__gc", std::function<void(CMainFrame*)>([](CMainFrame* ptr) {  }))
        .endClass();
}

/// 注册wxWidgets到脚本
void ScriptManager::registerwxWidgetsToLua(void)
{
    if(m_lua_state == NULL)
        return;

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxPoint>("wxPoint")
            //.addConstructor<void (*)(void)>()
            .addConstructor<void (*)(int,int)>()

            // 成员变量
            .addProperty("x", &wxPoint::x)
            .addProperty("y", &wxPoint::y)

            // 成员函数
            .addFunction("__gc", std::function<void(wxPoint*)>([](wxPoint*) { /* 空实现 */ }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxRealPoint>("wxRPoint")
            //.addConstructor<void (*)(void)>()
            .addConstructor<void (*)(double,double)>()

            // 成员变量
            .addProperty("x", &wxRealPoint::x)
            .addProperty("y", &wxRealPoint::y)

            .addFunction("__gc", std::function<void(wxRealPoint*)>([](wxRealPoint*) { /* 空实现 */ }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxSize>("wxSize")
            //.addConstructor<void (*)()>()
            .addConstructor<void (*)(int,int)>()

            // 成员函数
            .addFunction("GetHeight", &wxSize::GetHeight)
            .addFunction("GetWidth", &wxSize::GetWidth)
            .addFunction("SetHeight", &wxSize::SetHeight)
            .addFunction("SetWidth", &wxSize::SetWidth)

            .addFunction("__gc", std::function<void(wxSize*)>([](wxSize*) { /* 空实现 */ }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxRect>("wxRect")
            //.addConstructor<void (*)()>()
            .addConstructor<void (*)(int,int,int,int)>()
            .addConstructor<void (*)(const wxPoint &, const wxSize &)>()

            // 成员函数
            .addFunction("GetTopLeft", &wxRect::GetTopLeft)
            .addFunction("GetTopRight", &wxRect::GetTopRight)
            .addFunction("GetBottomLeft", &wxRect::GetBottomLeft)
            .addFunction("GetBottomRight", &wxRect::GetBottomRight)

            .addFunction("__gc", std::function<void(wxRect*)>([](wxRect*) { /* 空实现 */ }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxColour>("wxColour")
            //.addConstructor<void (*)()>()
            .addConstructor<void (*)(unsigned char,unsigned char,unsigned char,unsigned char)>()
            //.addConstructor<void (*)(unsigned long)>()

            // 成员函数
#if defined (WIN32)
            .addFunction("GetAlpha", &wxColour::GetAlpha)
            .addFunction("GetBlue", &wxColour::GetBlue)
            .addFunction("GetGreen", &wxColour::GetGreen)
            .addFunction("GetRed", &wxColour::GetRed)
#else
        .addFunction("GetAlpha", &wxColour::Alpha)
        .addFunction("GetBlue", &wxColour::Blue)
        .addFunction("GetGreen", &wxColour::Green)
        .addFunction("GetRed", &wxColour::Red)
#endif
        .addFunction("__gc", std::function<void(wxColour*)>([](wxColour*){ /* 空实现 */ }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxCStrData>("wxCStrData")
        .addFunction("str", &wxCStrData::operator const char*)
        //.addFunction("__gc", std::function<void(wxCStrData*)>([](wxCStrData* ptr) {  }))
        .endClass()

        // 然后注册 wxString
        .beginClass<wxString>("wxString")
        .addConstructor<void (*)(const char*)>()

        .addFunction("c_str", &wxString::c_str)
        .addFunction("empty", &wxString::empty)
        .addFunction("toutf8", &wxString::utf8_string)

        .addFunction("__gc", std::function<void(wxString*)>([](wxString*) { /* 空实现 */ }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginNamespace("MB")
            .addConstant("ANY", static_cast<int>(wxMouseButton::wxMOUSE_BTN_ANY))
            .addConstant("NONE", static_cast<int>(wxMouseButton::wxMOUSE_BTN_NONE))
            .addConstant("LEFT", static_cast<int>(wxMouseButton::wxMOUSE_BTN_LEFT))
            .addConstant("MIDDLE", static_cast<int>(wxMouseButton::wxMOUSE_BTN_MIDDLE))
            .addConstant("RIGHT", static_cast<int>(wxMouseButton::wxMOUSE_BTN_RIGHT))
            .addConstant("AUX1", static_cast<int>(wxMouseButton::wxMOUSE_BTN_AUX1))
            .addConstant("AUX2", static_cast<int>(wxMouseButton::wxMOUSE_BTN_AUX2))
        .endNamespace();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxEvent>("wxEvent")
            //.addConstructor<void (*)(int,wxEventType)>()
            .addFunction("__gc", std::function<void(wxEvent*)>([](wxEvent*) { /* 空实现 */ }))
        .endClass()
        .beginClass<wxMouseState>("wxMouseState")
            .addConstructor<void (*)()>()

            // 成员函数
            .addFunction("GetPosition",
                         (wxPoint (wxMouseState::*)() const) &wxMouseState::GetPosition)
            .addFunction("GetX", &wxMouseState::GetX)
            .addFunction("GetY", &wxMouseState::GetY)

            .addFunction("__gc", std::function<void(wxMouseState*)>([](wxMouseState*) { /* 空实现 */ }))
        .endClass()
        .deriveClass<wxMouseEvent, wxEvent>("wxMouseEvent")
            //.addParent<wxMouseState>()
            .addConstructor<void (*)(int)>()

            // 成员函数
            .addFunction("IsButton", &wxMouseEvent::IsButton)
            .addFunction("Button", &wxMouseEvent::Button)
            .addFunction("ButtonDClick", &wxMouseEvent::ButtonDClick)
            .addFunction("ButtonDown", &wxMouseEvent::ButtonDown)
            .addFunction("ButtonUp", &wxMouseEvent::ButtonUp)
            .addFunction("GetButton", &wxMouseEvent::GetButton)
            .addFunction("GetPosition",
                       (wxPoint (wxMouseEvent::*)() const) &wxMouseEvent::GetPosition)

            .addFunction("__gc", std::function<void(wxMouseEvent*)>([](wxMouseEvent*) { /* 空实现 */ }))
        .endClass();
}

/// 注册主绘图到脚本
void ScriptManager::registermaindrawsceneToLua(void)
{
    if(m_lua_state == NULL)
        return;

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<maindrawscene>("maindrawscene")
            // 成员函数
            .addFunction("LoadTextureFromFile", &maindrawscene::LoadTextureFromFile)
            .addFunction("DrawRectangle", &maindrawscene::DrawRectangle)
            .addFunction("DrawCircle", &maindrawscene::DrawCircle)
            .addFunction("DrawText1", &maindrawscene::DrawText1)
            .addFunction("DrawText2", &maindrawscene::DrawText2)
            .addFunction("DrawText3", &maindrawscene::DrawText3)
            .addFunction("DrawLine", &maindrawscene::DrawLine)
            .addFunction("DrawPoint", &maindrawscene::DrawPoint)
            .addFunction("DrawTexture", &maindrawscene::DrawTexture)

            .addFunction("__gc", std::function<void(maindrawscene*)>([](maindrawscene*) { /* 空实现 */ }))
        .endClass();
}

/// 注册结点到脚本中
void ScriptManager::registerNodeToLua(void)
{
    if(m_lua_state == NULL)
        return;

    luabridge::getGlobalNamespace(m_lua_state)
        .beginNamespace("MD")
            .addConstant("LEFT", static_cast<int>(MountDirection::DIRECTION_LEFT))
            .addConstant("RIGHT", static_cast<int>(MountDirection::DIRECTION_RIGHT))
        .endNamespace()
        .beginNamespace("NT")
            .addConstant("SWITCH", static_cast<int>(NodeType::NODE_SWITCH))
            .addConstant("SIGNAL", static_cast<int>(NodeType::NODE_SIGNAL))
            .addConstant("MOUNT", static_cast<int>(NodeType::NODE_MOUNT))
        .endNamespace()
        .beginNamespace("NOS")
            .addConstant("CHOSEN", static_cast<int>(NodeOperState::CHOSEN))
            .addConstant("LOCKED", static_cast<int>(NodeOperState::LOCKED))
            .addConstant("NORMAL", static_cast<int>(NodeOperState::NORMAL))
        .endNamespace()
        .beginNamespace("NSS")
            .addConstant("CLEAR", static_cast<int>(NodeSignalState::CLEAR))
            .addConstant("OCCUPY", static_cast<int>(NodeSignalState::OCCUPY))
            .addConstant("NOSIGNAL", static_cast<int>(NodeSignalState::NOSIGNAL))
        .endNamespace()
        .beginNamespace("SS")
            .addConstant("POSITIVE", static_cast<int>(SwitchState::POSITIVE))
            .addConstant("NEGATIVE", static_cast<int>(SwitchState::NEGATIVE))
        .endNamespace();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxPolygonEx>("wxPolygonEx")
            .addConstructor<void(*)()>()

            // 成员函数
            .addFunction("append", &wxPolygonEx::append)
            .addFunction("clear", &wxPolygonEx::clear)
            .addFunction("size", &wxPolygonEx::size)
            .addFunction("empty", &wxPolygonEx::empty)
            .addFunction("boundingRect", &wxPolygonEx::boundingRect)
            .addFunction("containsPoint", &wxPolygonEx::containsPoint)

            .addFunction("__gc", std::function<void(wxPolygonEx*)>([](wxPolygonEx*) { /* 空实现 */ }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<tagMountPoint>("tagMountPoint")
            .addConstructor<void(*)(wxString,wxPoint,WBaseNode*,int,int)>()

            // 注册成员变量
            .addProperty("pos", &tagMountPoint::pos)
            .addProperty("screenpos", &tagMountPoint::screenpos)
            .addProperty("node", &tagMountPoint::node)
            .addProperty("level", &tagMountPoint::level)
            .addProperty("direction", &tagMountPoint::direction)
            .addProperty("angle", &tagMountPoint::angle)
            .addProperty("name", &tagMountPoint::name)

            //.addFunction("__gc", std::function<void(tagMountPoint*)>([](tagMountPoint* ptr) {  }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<tagSwitchCondiItem>("tagSwitchCondiItem")
            .addConstructor<void(*)()>()

            // 注册成员变量
            .addProperty("switchnode", &tagSwitchCondiItem::switchnode)
            .addProperty("switchstate", &tagSwitchCondiItem::switchstate)

            //.addFunction("__gc", std::function<void(tagSwitchCondiItem*)>([](tagSwitchCondiItem* ptr) {  }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<tagRoute>("tagRoute")
        .addConstructor<void(*)()>()

        // 注册成员变量
        .addProperty("startLight", &tagRoute::startLight)
        .addProperty("endLight", &tagRoute::endLight)

        // 成员函数
        .addFunction("getAllSects", &tagRoute::getAllSects)
        .addFunction("getSectNodes", &tagRoute::getSectNodes)
        .addFunction("closeAllLights", &tagRoute::closeAllLights)

        //.addFunction("__gc", std::function<void(tagRoute*)>([](tagRoute* ptr) {  }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<tagRouteCondiItem>("tagRouteCondiItem")
            .addConstructor<void(*)()>()

            // 注册成员变量
            .addProperty("startLight", &tagRouteCondiItem::startLight)
            .addProperty("endLight", &tagRouteCondiItem::endLight)
            .addProperty("conflictsignals", &tagRouteCondiItem::conflictsignals)
            .addProperty("conflictswitch", &tagRouteCondiItem::conflictswitch)
            .addProperty("followswitch", &tagRouteCondiItem::followswitch)

            //.addFunction("__gc", std::function<void(tagRouteCondiItem*)>([](tagRouteCondiItem* ptr) {  }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<tagSLRouteNode>("tagSLRouteNode")
            .addConstructor<void(*)(WBaseNode*,const int)>()

            // 注册成员变量
            .addProperty("node", &tagSLRouteNode::node)
            .addProperty("MPointIndex", &tagSLRouteNode::MPointIndex)
            .addProperty("sectName", &tagSLRouteNode::sectName)
            .addProperty("sectPosition", &tagSLRouteNode::sectPosition)
            .addProperty("isLocked", &tagSLRouteNode::isLocked)
            .addProperty("isLighted", &tagSLRouteNode::isLighted)

            //.addFunction("__gc", std::function<void(tagSLRouteNode*)>([](tagSLRouteNode* ptr) {  }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<tagSectNode>("tagSectNode")
            .addConstructor<void(*)()>()

            // 成员函数
            .addFunction("isInLastSects", &tagSectNode::isInLastSects)
            .addFunction("isInNextSects", &tagSectNode::isInNextSects)
            .addFunction("getSectNodes", &tagSectNode::getSectNodes)
            .addFunction("clearLock", &tagSectNode::clearLock)
            .addFunction("getLastSects", &tagSectNode::getLastSects)
            .addFunction("getNextSects", &tagSectNode::getNextSects)
            .addFunction("getLastSect", &tagSectNode::getLastSect)
            .addFunction("getNextSect", &tagSectNode::getNextSect)

            // 注册成员变量
            .addProperty("sectname", &tagSectNode::sectname)
            .addProperty("operstate",
                 static_cast<int (tagSectNode::*)() const>(&tagSectNode::getSectOperState),
                 static_cast<void (tagSectNode::*)(int)>(&tagSectNode::setSectOperState)
                 )
            .addProperty("signalstate",
                 static_cast<int (tagSectNode::*)() const>(&tagSectNode::getSignalState),
                 static_cast<void (tagSectNode::*)(int)>(&tagSectNode::setSignalState)
                 )
            .addProperty("lastsignalstate",
                 static_cast<int (tagSectNode::*)() const>(&tagSectNode::getLastSignalState),
                 static_cast<void (tagSectNode::*)(int)>(&tagSectNode::setLastSignalState)
                 )
            .addProperty("accessrule",
                     static_cast<int (tagSectNode::*)() const>(&tagSectNode::getAccessRule),
                     static_cast<void (tagSectNode::*)(int)>(&tagSectNode::setAccessRule)
                     )
            .addProperty("curSwitchState",
                         static_cast<int (tagSectNode::*)() const>(&tagSectNode::getCurrentSwitchState),
                         static_cast<void (tagSectNode::*)(int)>(&tagSectNode::setCurrentSwitchState)
                         )

            //.addFunction("__gc", std::function<void(tagSectNode*)>([](tagSectNode* ptr) {  }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<WBaseNode>("WBaseNode")
            .addConstructor<void (*)(const wxString&)>()

            // 成员函数
            .addFunction("getName", &WBaseNode::getName)
            .addFunction("setNodeType", &WBaseNode::setNodeType)
            .addFunction("getNodeType", &WBaseNode::getNodeType)
            .addFunction("setOperState", &WBaseNode::setOperState)
            .addFunction("getOperState", &WBaseNode::getOperState)
            .addFunction("setDeviceID", &WBaseNode::setDeviceID)
            .addFunction("getDeviceID", &WBaseNode::getDeviceID)
            .addFunction("setSignalState", &WBaseNode::setSignalState)
            .addFunction("getSignalState", &WBaseNode::getSignalState)
            .addFunction("setPosition", &WBaseNode::setPosition)
            .addFunction("getPosition", &WBaseNode::getPosition)
            .addFunction("getMountPointByDir", &WBaseNode::getMountPointByDir)
            .addFunction("isExistMountNode", &WBaseNode::isExistMountNode)
            .addFunction("getScreenPosition", &WBaseNode::getScreenPosition)
            .addFunction("getBoundingRect", &WBaseNode::getBoundingRect)
            .addFunction("getColourByState", &WBaseNode::getColourByState)
            .addFunction("getTextColourByState", &WBaseNode::getTextColourByState)

            //.addFunction("__gc", std::function<void(WBaseNode*)>([](WBaseNode* ptr) {  }))
        .endClass()
        .deriveClass<WMountNode, WBaseNode>("WMountNode")
            .addConstructor<void(*)(const wxString&)>()

            .addStaticFunction("castFromBase", +[](WBaseNode* base) {
                return dynamic_cast<WMountNode*>(base);
            })

            //.addFunction("__gc", std::function<void(WMountNode*)>([](WMountNode* ptr) {  }))
        .endClass()
        .deriveClass<WSignalLampNode, WBaseNode>("WSignalLampNode")
            .addConstructor<void(*)(const wxString&)>()

            // 成员函数
            .addFunction("drawName", &WSignalLampNode::drawName)
            .addFunction("setRouteType", &WSignalLampNode::setRouteType)
            .addFunction("getRouteType", &WSignalLampNode::getRouteType)

            .addStaticFunction("castFromBase", +[](WBaseNode* base) {
                return dynamic_cast<WSignalLampNode*>(base);            
            })
            //.addFunction("__gc", std::function<void(WSignalLampNode*)>([](WSignalLampNode* ptr) {  }))
        .endClass()
        .deriveClass<WSwitchNode, WBaseNode>("WSwitchNode")
            .addConstructor<void(*)(const wxString&)>()

            // 成员函数
            .addFunction("initSwitchState", &WSwitchNode::initSwitchState)
            .addFunction("setSwitchState", &WSwitchNode::setSwitchState)
            .addFunction("getSwitchState", &WSwitchNode::getSwitchState)

            .addStaticFunction("castFromBase", +[](WBaseNode* base) {
                return dynamic_cast<WSwitchNode*>(base);
            })

            //.addFunction("__gc", std::function<void(WSwitchNode*)>([](WSwitchNode* ptr) {  }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<WNodeManager>("WNodeManager")
            .addConstructor<void (*)()>()

            // 成员函数
            .addFunction("deleteAllNodes", &WNodeManager::deleteAllNodes)
            .addFunction("getNodeByName", &WNodeManager::getNodeByName)
            .addFunction("getNodeByPoint", &WNodeManager::getNodeByPoint)
            .addFunction("addMountNode", &WNodeManager::addMountNode)
            .addFunction("clear", &WNodeManager::clear)
            .addFunction("setMouseCursor", &WNodeManager::setMouseCursor)
            .addFunction("loadJsonConfig", &WNodeManager::loadJsonConfig)
            .addFunction("getRoute", &WNodeManager::getRoute)
            .addFunction("addRoute", &WNodeManager::addRoute)
            .addFunction("deleteRoute", &WNodeManager::deleteRoute)
            .addFunction("cancelRoute", &WNodeManager::cancelRoute)
            .addFunction("getAllRoutes", &WNodeManager::getAllRoutes)
            .addFunction("getSect", &WNodeManager::getSect)
            .addFunction("controlTheSignalLamp", &WNodeManager::controlTheSignalLamp)
            .addFunction("getSectNameByDeviceID", &WNodeManager::getSectNameByDeviceID)
            .addFunction("checkRoute", &WNodeManager::checkRoute)
            .addFunction("closeRouteAllLights", &WNodeManager::closeRouteAllLights)
            .addFunction("printSect", &WNodeManager::printSect)
            .addFunction("setSectOperState", &WNodeManager::setSectOperState)
            .addFunction("setSectSignalState", &WNodeManager::setSectSignalState)
            .addFunction("sendSignal", &WNodeManager::sendSignal)
            .addFunction("autoDeleteSelectedRoute", &WNodeManager::autoDeleteSelectedRoute)
            .addFunction("startTimer", &WNodeManager::startTimer)
            .addFunction("stopTimer", &WNodeManager::stopTimer)
            .addFunction("stopAllTimer", &WNodeManager::stopAllTimer)

            //.addFunction("__gc", std::function<void(WNodeManager*)>([](WNodeManager* ptr) {  }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<LocoManager>("LocoManager")
            .addConstructor<void (*)()>()

            // 成员函数
            .addFunction("addLoco", &LocoManager::addLoco)
            .addFunction("addLocos", &LocoManager::addLocos)
            .addFunction("moveLoco", &LocoManager::moveLoco)
            .addFunction("moveLoco2", &LocoManager::moveLoco2)
            .addFunction("changeLoco", &LocoManager::changeLoco)
            .addFunction("couplingLoco", &LocoManager::couplingLoco)
            .addFunction("uncouplingLoco", &LocoManager::uncouplingLoco)
            .addFunction("deleteLocoByName", &LocoManager::deleteLocoByName)
            .addFunction("deleteLocoById", &LocoManager::deleteLocoById)
            .addFunction("deleteLocoByTrack", &LocoManager::deleteLocoByTrack)
            .addFunction("deleteAllLocos", &LocoManager::deleteAllLocos)
            .addFunction("getSelectedTrackName", &LocoManager::getSelectedTrackName)
            .addFunction("getSelectedLocoName", &LocoManager::getSelectedLocoName)
            .addFunction("getSelectedLocoId", &LocoManager::getSelectedLocoId)

            //.addFunction("__gc", std::function<void(LocoManager*)>([](LocoManager* ptr) {  }))
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<GuiManager>("GuiManager")
        .addConstructor<void (*)()>()

        // 成员函数
        .addFunction("resetAllNodes", &GuiManager::resetAllNodes)
        //.addFunction("__gc", std::function<void(GuiManager*)>([](GuiManager* ptr) {  }))
        .endClass();
}

/// 建立一个空函数
/*luabridge::LuaRef ScriptManager::createEmptyCallback(void)
{
    // 捕获 this 指针以访问 m_lua_state
    static luabridge::LuaRef emptyCallback = [this]() -> luabridge::LuaRef {
        if (luaL_dostring(m_lua_state, "return function(name,state) end") == LUA_OK) {
            luabridge::LuaRef func(luabridge::LuaRef::fromStack(m_lua_state, -1));
            lua_pop(m_lua_state, 1);
            return func;
        }
        return luabridge::LuaRef(m_lua_state); // 返回 nil
    }();

    return emptyCallback;
}*/
